/**
 * 
 */
package qy.qyalgotrader.eventprof;

import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.util.Map;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.collections4.map.ListOrderedMap;

import qy.jalgotrade.dataseries.BarDataSeries;
import qy.jalgotrade.eventprof.Predicate;
import qy.jalgotrade.technical.BollingerBands;
import qy.jalgotrade.technical.CrossUils;
import qy.qyalgotrader.technical.CDTS;
import qy.qyalgotrader.utils.CommonDataUtils;

/**
 * @author qy
 *
 */
public class CdtsPredicate extends Predicate {

	// @formatter:off
	public static final Map<String, Object> DEFAULT_OPT_PARAMS = MapUtils.putAll(new ListOrderedMap<>(), new Object[][] {
		{"ctBollPeriod", 1200}, {"ctBollStd", 2.0}, // CT(Convergence & Divergence (VWAP) of Time-Sharing Diagram) BOLL
		{"fastEma", 12}, {"slowEma", 26}, {"signalEma", 9}, {"diffSignal", false}, // MACD
	});
	// @formatter:on

	private CDTS __cdts;

	private BollingerBands __ctBoll;

	// CT BOLL:
	private int __ctBollPeriod;

	private double __ctBollStd;

	private LocalDate __currTd;

	private boolean __intraday1stSig;

	/**
	 * 
	 * @param bards
	 * @param optParams
	 * @throws Exception
	 */
	public CdtsPredicate(BarDataSeries bards, Map<String, Object> optParams) throws Exception {

		super();
		__cdts = new CDTS(bards);
		// CT BOLL:
		__ctBollPeriod = (int) optParams.getOrDefault("ctBollPeriod", DEFAULT_OPT_PARAMS.get("ctBollPeriod"));
		__ctBollStd = (double) optParams.getOrDefault("ctBollStd", DEFAULT_OPT_PARAMS.get("ctBollStd"));
		__ctBoll = new BollingerBands(__cdts, __ctBollPeriod, __ctBollStd);
		__currTd = null;
		__intraday1stSig = true;
	}

	@Override
	public boolean eventOccurred(String instrument, BarDataSeries bards) {

		ZonedDateTime dm = CommonDataUtils.toMarketDatetime(bards.__getitem__(-1).getDateTime());
		if (__currTd == null) {
			__currTd = dm.toLocalDate();
		} else {
			if (!__currTd.equals(dm.toLocalDate())) {
				__currTd = dm.toLocalDate();
				__intraday1stSig = true;
			}
		}

		// 检查各技术指标序列均可用: CT, CT-BOLL:
		if (__cdts.__len__() < 1 || Double.isNaN(__cdts.__getitem__(-1))
				|| Double.isNaN(__ctBoll.getUpperBand().__getitem__(-1))) {
			return false;
		}

		if (CrossUils.crossAbove(__cdts, __ctBoll.getUpperBand()) > 0
				&& __intraday1stSig) {
			__intraday1stSig = false;
			return true;
		} else {
			return false;
		}
	}
}
